#include "EntityX.h"
#include "IRenderSystem.h"
#include "Node.h"
#include "D3D9Mapping.h"
#include "Paras.h"
//
namespace Euclid
{
	EntityX::EntityX()
		:	_mesh(0), _materials(0), _numMaterial(0), _xMaterialBuffer(0),
			_textures(0)
	{
		_type = "EntityX";
		_device = Paras::getSingletonPtr()->_device;
	}

	EntityX::~EntityX()
	{
		destroy();
	}

	bool EntityX::create()
	{
		return true;
	}

	void EntityX::destroy()
	{
		for (unsigned int i = 0; i < _numMaterial; ++i)
		{
			if (_textures[i])
			{
				_textures[i]->Release();
				_textures[i] = 0;
			}
		}
		delete[] _textures;

		if (_mesh)
		{
			_mesh->Release();
			_mesh = 0;
		}
	}

	void EntityX::preRender()
	{
		if (_currentNode)
		{
			_renderSystem->setRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
			//
			_renderSystem->setRenderState(D3DRS_LIGHTING, true);
			//
			_renderSystem->setRenderState(D3DRS_AMBIENT, 0xffffffff);
			//
			_renderSystem->setRenderState(D3DRS_ZENABLE, true);
			//
			_currentNode->_updateFromParent();
			D3DXMATRIX m = D3D9Mapping::makeD3DXMatrix(_currentNode->_getFullTransform());
			_renderSystem->setWorldMatrix(&m);
		}
	}

	void EntityX::postRender()
	{
		//
		D3DXMATRIX m = D3D9Mapping::makeD3DXMatrix(Euler::Matrix4::IDENTITY);
		_renderSystem->setWorldMatrix(&m);
	}

	void EntityX::render()
	{
		//
		if (!_mesh)
		{
			return;
		}

		//
		HRESULT hr;
		for (unsigned int i = 0; i < _numMaterial; ++i)
		{
			//
			_device->SetMaterial(_materials + i);

			//
			_device->SetTexture(0, _textures[i]);

			//
			hr = _mesh->DrawSubset(i);
			if (FAILED(hr))
			{
				return;
			}
		}
	}

	bool EntityX::loadMeshFromX( const std::string& file, unsigned long flag /*= D3DXMESH_SYSTEMMEM*/ )
	{
		//
		HRESULT hr;
		hr = D3DXLoadMeshFromX(file.c_str(), flag, _device, 0, &_xMaterialBuffer, 0, &_numMaterial, &_mesh);
		if (FAILED(hr))
		{
			return false;
		}

		//
		if (!_xMaterialBuffer)
		{
			return false;
		}

		//
		_materials = new D3DMATERIAL9[_numMaterial];

		//
		_textures = new LPDIRECT3DTEXTURE9[_numMaterial];

		//
		D3DXMATERIAL* mat = 0;
		mat = (D3DXMATERIAL*)_xMaterialBuffer->GetBufferPointer();

		//

		std::string tiger;
		Buddha::FileSystem::getSingletonPtr()->getDataDirectory(tiger);
		for(unsigned int i = 0; i < _numMaterial; ++i)
		{
			//
			_materials[i] = mat[i].MatD3D;
			_materials[i].Ambient = _materials[i].Diffuse;

			//
			tiger += "\\image\\";
			tiger += mat[i].pTextureFilename;
			hr = D3DXCreateTextureFromFile( _device, tiger.c_str(), &_textures[i] );
			if (FAILED(hr))
			{
				return false;
			}
		}

		//
		_xMaterialBuffer->Release();

		//
		return true;
	}
}
